
#pragma once

#include<cstdio>
#include<iostream>
#include<string>
#include<cstdarg>
#include<ctime>
#include<unistd.h>
#include<fstream>
#include"LockGuard.hpp"

bool IsSave=false;
const std::string logname="log.txt"; 

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

void SaveFile(const std::string&);


enum LEVEL
{
    DEBUG=0,
    INFO,
    WARNNING,
    ERROR,
    FATAL
};

std::string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG: return "debug";
    case INFO: return "info";
    case WARNNING: return "warnning";
    case ERROR: return "error";
    case FATAL: return "fatal";
    default: return "unknown";
    }
}

std::string GetTimeString()
{
    time_t curtime=time(nullptr);
    struct tm* format_time=localtime(&curtime);
    if(format_time==nullptr) return "None";
    char time_buffer[1024]={0};
    snprintf(time_buffer,sizeof(time_buffer),"%d-%d-%d %d:%d:%d",
                format_time->tm_year+1900,
                format_time->tm_mon,
                format_time->tm_mday,
                format_time->tm_hour,
                format_time->tm_min,
                format_time->tm_sec);
    return time_buffer;
}

void LogMessage(const char* file, int line, int level, const char* format, ...)
{
    std::string levelstring=LevelToString(level);


    va_list arg;
    char buffer[1024]={0};
    va_start(arg,format);
    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);

    std::string timestring=GetTimeString();

    std::string logstr=
    "["+timestring + "]" + "[" +levelstring + "]" +"[" + file+"-"+std::to_string(line) + "]  " + buffer+"\n";

    if(IsSave)
    {
        SaveFile(logstr);
    }
    else
    {
        LockGuard lock(mutex);
        std::cout<<logstr;
    }
}

void SaveFile(const std::string& str)
{
    std::ofstream out(logname,std::ios::app);
    if(!out.is_open())
    {
        IsSave=false;
        LogMessage(__FILE__,__LINE__,ERROR,"file open fail!");
        return;
    }
    out << str;
    out.close();

}

#define LOG(level, format, ...) do{LogMessage(__FILE__, __LINE__, level, format, ##__VA_ARGS__);}while(0)

#define EnableFile() do{IsSave=true;}while(0)

#define EnableScreen() do{IsSave=false;}while(0)